package base.thread_demo.demo10;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/**
 *  使用 ThreadLocal 对 TopicDao 中conn这个非线程安全的变量进行改造.
 *
 * 当然这个例子本身很粗糙，将 Connection 的 ThreadLocal 直接放在DAO只能做到本DAO的多个方法
 * 共享Connection时不发生线程安全问题，
 * 但是无法和其他DAO共用同一个Connection，要做到同一事务多DAO共享同一个Connection，
 * 必须在一个共同的外部类使用ThreadLocal保存Connection。
 *
 * 大师这个实力基本上说明了Spring对有状态类线程安全化的解决思路。
 */
public class TopicDao {

    //多线程环境下共享一个非线程安全的变量
    private Connection conn;

    public void addTopic() throws SQLException {
        //引用非线程安全变量
        Statement stat = conn.createStatement();
    }
}

class TopicDao2 {
    //使用ThreadLocal保存Connection变量
    private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>();

    public static Connection getConnection() throws SQLException{
        /*
         * 如果connThreadLocal没有本线程对应的Connection，创建一个新的Connection。并将其保存到线程本地变量中。
         */
        if(connThreadLocal.get() == null){
            Connection conn = DriverManager.getConnection("url", "user", "password");
            connThreadLocal.set(conn);
            return conn;
        }else{
            return connThreadLocal.get();
        }
    }

    public void addTopic() throws SQLException{
        /*
         * 从ThreadLocal中获取线程对应的Connection
         */
        Statement stat = getConnection().createStatement();
    }
}
